open Card;;
open Hand;;
open List;;
open Common;;
open Deck;;
open Player;;

type draw = {
  flop  : card*card*card;
  turn  : card;
  river : card};;







type table = {
  mutable deck : deck ref;
  mutable pot : int;
  mutable draw :card list;
  mutable playing_players : players;
  mutable registred_players : players;
  mutable current_bet : int;
  mutable big_blind : int;
  mutable small_blind : int;
  mutable ante : int};;





let set_players_position player_list =
  let rec set_players_position_none player_list = 
    match player_list with 
      | h::t -> h.position <- None; set_players_position_none t
      | [] -> () in
  let rec set_player_dealer player_list = 
    match player_list with 
      | []    ->  failwith "set_player_position : not enought players"
      | l::[] -> l.dealer <- true;
      | h::t  -> h.dealer <- false; set_player_dealer t in
    match player_list with
      | f::s::[] -> 
	  f.position <- Small_blind; 
	  s.position <- Big_blind;
	  set_player_dealer player_list
      | f::s::t  ->
	  f.position <- Small_blind;
	  s.position <- Big_blind; 
	  set_players_position_none t;
	  set_player_dealer player_list
      | h::[] -> failwith "set_player_position : not enought players"
      | []    -> failwith "set_player_position : not enought players";;


let start_party player_list  bb sm an= 
  let deck = init_deck() in
    set_players_position player_list;
    { deck = ref deck; 
      pot = 0;
      draw = [];
      playing_players = player_list;
      registred_players = player_list;
      current_bet = 0;
      big_blind = bb;
      small_blind = sm;
      ante = an
    }
      
    


let print_table table =
 let players = table.playing_players in
 print_line();
 print_string ("The daw is "^(string_of_card_list table.draw)^"\n");
 print_string ("Current bet is "^(string_of_int table.current_bet)^"\n");
 print_string ("The pot "^(string_of_int table.pot)^"\n");
 for i=0 to (List.length players)-1
 do
  let cp = List.nth players i in
    print_string cp.name;
    print_string (" last move : "^(string_of_action cp.last_move)); 
    match cp.last_move with 
    | Raise _ -> ()
    | _       -> print_string (" Last bet : "^string_of_int cp.last_bet^"\n")
 done;;
 

let bet_round table = 
  let same_bet p1 = p1.last_bet = table.current_bet in
  let i  = ref (-1) in
    while  ((List.length table.playing_players) > 1) || (not (for_all same_bet table.playing_players) )
    do
      i := succ !i;
      print_table table;
      let current_player = (next_circular table.playing_players !i) in
      let move = play  table.current_bet current_player in
	match move with
	  | Fold ->  table.playing_players <- remove_list_element table.playing_players current_player;
	  | Check -> ()
	  | Call -> table.pot <- table.pot + table.current_bet
	  | Raise amount -> 
	      (
	      	table.current_bet <- amount;
		table.pot <- table.pot + amount	
	      )
    done;;

let give_cards table = 
  let players = table.playing_players in
    for i = 0 to (2*( length players))-1
    do
      add_card (next_circular players i) (get_card table.deck)
    done;;

let remove_cards table = 
  let players = table.playing_players in
    for i = 0 to (2*( length players))-1
    do
      add_card (next_circular players i) (get_card table.deck)
    done;;

let start_hand table = 
  let pay_ante   = function
    | h::t -> h.chips <- h.chips - table.ante; table.pot <- table.pot + table.ante
    | [] -> () in
  let sb_player = (next_circular table.playing_players 0) in
  let bb_player = (next_circular table.playing_players 1) in
    table.deck <- ref (init_deck());
    give_cards table ;
    print_string "New hand !! \nFirst and second player pay the Small blind and the Big blind\n";
    table.pot <- table.small_blind + table.big_blind;
    sb_player.chips <-  sb_player.chips - table.small_blind;
    bb_player.chips <-  bb_player.chips - table.big_blind;
    if table.ante > 0 then
      (
	print_string "Everybody pay the ante\n";
	pay_ante table.playing_players
      );
    table.draw <- [];;

let stop_hand table = 
  (*Declare the winner*)
  let winner,hand = find_winner table.playing_players in
    winner.chips <- winner.chips+table.pot;
    print_string ("And the WINNER with a "^(Hand.string_of_hand hand)^"is "^winner.name^" !\n");
    
    table.registred_players <- List.map (rm_card) (table.registred_players);
    table.playing_players <- table.registred_players;;

let hand  table =
  print_string "Pre-flop !\n";
  bet_round table;
  if (List.length table.playing_players)>1 
  then(
    print_string "Flop !\n";
    burn_card table.deck;
    for i = 1 to 3 do  table.draw <- (get_card table.deck)::table.draw done; 
    bet_round table;
  );
  if (List.length table.playing_players)>1 
  then( 
    print_string "Turn !\n";
    burn_card table.deck;
    table.draw <- (get_card table.deck)::table.draw;
    bet_round table
  );
  if (List.length table.playing_players)>1 
  then(       
    print_string "River !\n" ;
    burn_card table.deck;
    table.draw <- (get_card table.deck)::table.draw;
    bet_round table
  );;







let party player_list sb bb ante= 
  print_line();
  let table = start_party player_list  bb sb ante in
    while (List.length table.registred_players)>1
    do
      start_hand table;
      hand table;
      stop_hand table;
    done;
    print_string "This table is closed because there not enoutgh player\n";;


    
  

    
